COM_ADDR	EQU	0263H
T0_ADDR		EQU	0260H
T1_ADDR		EQU	0261H
T2_ADDR		EQU	0262H

IO8259_0	EQU	0250H
IO8259_1	EQU	0251H

_STACK 	SEGMENT STACK
	DW 	100 DUP(?)
_STACK 	ENDS

CODE 	SEGMENT
	ASSUME 	CS:CODE, SS:_STACK
START:  CLI
				CALL		Init8259			;调用8259初始化函数
				CALL		WriIntver			;中断向量

				MOV  DX,COM_ADDR			;端口地址超8位，先送至dx
				MOV  AL,90H						;计数器2，读写低8位，方式0，二进制计数
				OUT  DX,AL						;将控制字写入8253
A1:			MOV  DX,T2_ADDR				;将计数器2地址送入dx
				MOV  AL,05H						;先写入低字节，计数初值为6
				OUT  DX,AL						;写入计数初值
				STI										;允许中断发生
				HLT										;暂停
				JMP  A1

IRQ7:		MOV  AH,02H						;设置单字符显示模式
				MOV  DL,4DH						;设置显示字符为M
				INT  21H							;向屏幕输出字符
				MOV  DL,20H						;设置显示字符为空格
				INT  21H							;向屏幕输出字符

				MOV  DX,IO8259_0			;写操作命令字OCW2,设置中断结束方式
				MOV  AL,20H						;一般EOI命令，全嵌套方式
				OUT  DX,AL						;向8259发出中断结束命令EOI
				IRET
				
Init8259	PROC	NEAR
		MOV	DX,IO8259_0
		MOV	AL,13H
		OUT	DX,AL      ;13H->ICW1：8086模式、需要初始化ICW4
		MOV	DX,IO8259_1
		MOV	AL,08H
		OUT	DX,AL  ;08H->ICW2, 也就是IR0的中断向量是08H，…，IR7的中断向量是0FH
		MOV	AL,09H
		OUT	DX,AL    ;09H->ICW4
		MOV	AL,07FH
		OUT	DX,AL   ;7FH->OCW1(IMR),仅允许IR7中断
		RET
Init8259	ENDP

WriIntver	PROC	NEAR
		PUSH	ES
		MOV	AX,0
		MOV	ES,AX
		MOV	DI,20H + 7 * 4        ;IR7中断向量是 8（ICW2）+7
					;中断向量对应的物理地址 = 中断向量 * 4
					;IR7对应的物理地址=8*4(20H) + 7 * 4
					;ES:DI --- 0000H:3CH(20H+1CH)
		LEA	AX,IRQ7   ;IR7中断入口地址对应的段内偏移
		STOSW    ;4个字节，段内偏移在前，段后偏移
		MOV	AX,CS  ;段地址
		STOSW
		POP	ES
		RET
WriIntver	ENDP

CODE 	ENDS
     	END 	START

